home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1996 #15 / Monster Media Number 15 (Monster Media)(July 1996).ISO / prog_pas / xport11.zip / NETFILEP.PAS < prev    next >
Pascal/Delphi Source File  |  1995-12-22  |  22KB  |  502 lines

  1. {*********************************************************************}
  2. {*                        N E T F I L E                              *}
  3. {*-------------------------------------------------------------------*}
  4. {*    Task          : Implements network supporting file functions.  *}
  5. {*-------------------------------------------------------------------*}
  6. {*    Author        : Michael Tischer                                *}
  7. {*    Developed on  : 09/07/91                                       *}
  8. {*    Last update   : 01/29/92                                       *}
  9. {*********************************************************************}
  10. {$F+}
  11. unit NetFileP;
  12.  
  13. interface
  14.  
  15. uses Crt, Dos;             { Add CRT, DOS and DDPlus units }
  16.  
  17. const {-- Types of file access available -----------------------------}
  18.  
  19.       fm_r    = 0;                                        { Read-only }
  20.       fm_w    = 1;                                       { Write-only }
  21.       fm_rw   = 2;             { Read and write in normal Pascal mode }
  22.  
  23.       {-- Types of file protection -----------------------------------}
  24.  
  25.       sm_comp = $00;         { Compatibility mode, no file protection }
  26.       sm_rw   = $10;            { Read and write prohibited by others }
  27.       sm_r    = $20;   { Read by others permitted, writing prohibited }
  28.       sm_w    = $30;        { Reading and writing by others permitted }
  29.       sm_no   = $40;        { All permitted, protected by record lock }
  30.  
  31.       {-- Possible errors during procedure calls ---------------------}
  32.  
  33.       NE_OK            = $00;                              { No error }
  34.       NE_FileNotFound  = $02;                 { Error: File not found }
  35.       NE_PathNotFound  = $03;                 { Error: Path not found }
  36.       NE_TooManyFiles  = $04;            { Error: Too many open files }
  37.       NE_AccessDenied  = $05;          { Error: Access to file denied }
  38.       NE_InvalidHandle = $06;            { Error: Invalid file handle }
  39.       NE_AccessCode    = $07;            { Error: Illegal access code }
  40.       NE_Share         = $20;             { Violation of Share rights }
  41.       NE_Lock          = $21;      { Error while (un)locking a record }
  42.       NE_ShareBuffer   = $24;                 { Share buffer overflow }
  43.  
  44. var NetError : integer;             { Error number from DOS interrupt }
  45.  
  46. function ShareInst : boolean;                      { Share installed? }
  47.  
  48. function NetErrorMsg( Number : word ) : string;       { Error message }
  49.  
  50. procedure NetReset(     FName  : string;                  { Open file }
  51.                         AMode  : integer;
  52.                         RecS   : word;
  53.                     var DFile );
  54.  
  55. procedure NetRewrite(     FName  : string;            { Open new file }
  56.                           AMode  : integer;
  57.                           RecS   : word;
  58.                       var DFile );
  59.  
  60. procedure NetClose( var DFile );                         { Close file }
  61.  
  62. function NetLock( var DFile;                        { Lock file range }
  63.                       RecNo  : longint;
  64.                       RngNum : longint ) : boolean;
  65.  
  66. function NetUnlock( var DFile;                    { Unlock file range }
  67.                         RecNo  : longint;
  68.                         RngNum : longint ) : boolean;
  69.  
  70. function Is_NetOpen( var DFile ) : boolean;           { Is file open? }
  71.  
  72. function Is_NetWriteOk( var DFile ) : boolean; { Writing to file O.K. }
  73.  
  74. function Is_NetReadOk( var DFile ) : boolean; { Reading from file O.K.}
  75.  
  76. {-- The Read, Write and Seek procedures only work with files set in  -}
  77. {-- input-output mode. The following procedures must be used if      -}
  78. {-- files must be opened in other modes.                             -}
  79.  
  80. procedure NetWrite( var DFile;                      { Write to a file }
  81.                     var FData );
  82.  
  83. procedure NetRead( var DFile;                      { Read from a file }
  84.                    var FData );
  85.  
  86. procedure NetSeek( var DFile;                 { Position file pointer }
  87.                        RecNo : longint );
  88.  
  89. implementation
  90.  
  91. const {-- Function numbers for DOS calls -----------------------------}
  92.  
  93.       FCT_OPEN     = $3D;         { Function: Open file with handle   }
  94.       FCT_CLOSE    = $3E;         { Function: Close file with handle  }
  95.       FCT_CREATE   = $3C;         { Function: Create file with handle }
  96.       FCT_WRITE    = $40;         { Function: Write to file           }
  97.       FCT_READ     = $3F;         { Function: Read from file          }
  98.       FCT_LSEEK    = $42;         { Function: Set file pointer        }
  99.       FCT_REC_LOCK = $5C;         { Function: Record locking          }
  100.  
  101.       {-- Function & interrupt numbers for other interrupt calls -----}
  102.  
  103.       MULTIPLEX    = $2F;                       { Multiplex interrupt }
  104.       FCT_SHARE    = $1000;                  { Install text for Share }
  105.  
  106.       {-- Turbo Pascal file identifiers ------------------------------}
  107.  
  108.       fmClosed     = $D7B0;                             { File closed }
  109.       fmInput      = $D7B1;                 { File opened for reading }
  110.       fmOutput     = $D7B2;                 { File opened for writing }
  111.       fmInOut      = $D7B3;     { File opened for reading and writing }
  112.  
  113. {*********************************************************************}
  114. {* ShareInst   : Installs test for Share.                            *}
  115. {* Input       : None                                                *}
  116. {* Output      : TRUE if Share is installed                          *}
  117. {* Global var. : NetError/W (error status after call)                *}
  118. {*********************************************************************}
  119.  
  120. function ShareInst : boolean;
  121.  
  122. var regs   : registers;      { Processor registers for interrupt call }
  123.  
  124. begin
  125.  regs.ax := FCT_SHARE;                     { Test for installed Share }
  126.  intr( MULTIPLEX, regs );                  { Call multiplex interrupt }
  127.  ShareInst := ( regs.al = $FF );                      { Return result }
  128.  NetError := NE_OK;                                        { No error }
  129. end;
  130.  
  131. {*********************************************************************}
  132. {* NetErrorMsg : Error message text.                                 *}
  133. {* Input       : Error number                                        *}
  134. {* Output      : Meaning                                             *}
  135. {*********************************************************************}
  136.  
  137. function NetErrorMsg( Number : word ) : string;
  138.  
  139. var Sdummy : string;
  140.  
  141. begin
  142.   case Number of
  143.     NE_OK            : NetErrorMsg := 'No error';
  144.     NE_FileNotFound  : NetErrorMsg := 'File not found';
  145.     NE_PathNotFound  : NetErrorMsg := 'Path not found';
  146.     NE_TooManyFiles  : NetErrorMsg := 'Too many files open';
  147.     NE_AccessDenied  : NetErrorMsg := 'File access denied';
  148.     NE_InvalidHandle : NetErrorMsg := 'Invalid file handle';
  149.     NE_AccessCode    : NetErrorMsg := 'Illegal access code';
  150.     NE_Share         : NetErrorMsg := 'Violation of Share rights';
  151.     NE_Lock          : NetErrorMsg := 'Error during record lock';
  152.     NE_ShareBuffer   : NetErrorMsg := 'Share buffer overflow';
  153.     else               begin
  154.                          str( Number, Sdummy );
  155.                          NetErrorMsg := 'DOS error: ' + Sdummy;
  156.                        end;
  157.   end;
  158. end;
  159.  
  160. {*********************************************************************}
  161. {* NetCreate   : Creates a file.                                     *}
  162. {* Input       : Filename, opening mode, record size                 *}
  163. {* Output      : Opened file                                         *}
  164. {* Global var. : NetError/W (error status after call)                *}
  165. {*********************************************************************}
  166.  
  167. procedure NetRewrite(     FName  : string;
  168.                           AMode  : integer;
  169.                           RecS   : word;
  170.                       var DFile );
  171.  
  172. var regs   : registers;      { Processor registers for interrupt call }
  173.     FName2 : string;                      { Filename for local access }
  174.  
  175. begin
  176.   FName2 := FName + #0;                   { Copy and prepare filename }
  177.   with regs do
  178.     begin
  179.       ds := seg( FName2[ 1 ] );                     { Assign filename }
  180.       dx := ofs( FName2[ 1 ] );
  181.       ah := FCT_CREATE;                  { Function number: Open file }
  182.       cx := 0 ;                                      { File attribute }
  183.       msdos( regs );                                 { Interrupt call }
  184.       if ( ( flags and fcarry ) = 0 ) then         { Open successful? }
  185.         begin
  186.           bx := ax;                           { Handle in register BX }
  187.           ah := FCT_CLOSE;              { Function number: Close file }
  188.           msdos( regs );
  189.           if ( ( flags and fcarry ) = 0 ) then    { Close successful? }
  190.             NetReset( FName, AMode, Recs, DFile )         { Open file }
  191.           else
  192.             NetError := ax;                       { Note error number }
  193.         end
  194.       else
  195.         NetError := ax;                           { Note error number }
  196.     end;
  197. end;
  198.  
  199. {*********************************************************************}
  200. {* NetReset    : Opens a specific file.                              *}
  201. {* Input       : Filename, open mode, record size                    *}
  202. {* Output      : Opened file                                         *}
  203. {* Global var. : NetError/W (error status after call)                *}
  204. {*********************************************************************}
  205.  
  206. procedure NetReset(     FName  : string;
  207.                         AMode  : integer;
  208.                         RecS   : word;
  209.                     var DFile );
  210.  
  211. var regs : registers;        { Processor registers for interrupt call }
  212.  
  213. begin
  214.   FName := FName + #0;                    { Filename must end with #0 }
  215.   with regs do
  216.     begin
  217.       ds := seg( FName[ 1 ] );                      { Assign filename }
  218.       dx := ofs( FName[ 1 ] );
  219.       ah := FCT_OPEN;                    { Function number: Open file }
  220.       al := AMode;          { Status byte for access mode and locking }
  221.       msdos( regs );                                 { Interrupt call }
  222.       if ( ( flags and fcarry ) = 0 ) then         { Open successful? }
  223.         begin
  224.           NetError := NE_OK;                               { No error }
  225.           with filerec( DFile ) do
  226.             begin
  227.               move( FName[ 1 ], filerec( DFile ).Name,     { Assign   }
  228.                     length( FName ) );                     { filename }
  229.               Handle := ax;                             { File handle }
  230.               RecSize := RecS;                  { Specify record size }
  231.               case ( AMode and $0F ) of    { Specify Pascal file mode }
  232.                 fm_r   : Mode := fmInput;
  233.                 fm_w   : Mode := fmOutput;
  234.                 fm_rw  : Mode := fmInOut;
  235.               end;
  236.             end;
  237.         end
  238.       else
  239.         begin
  240.           NetError := ax;                         { Note error number }
  241.           filerec( DFile ).Mode := fmClosed;        { File not opened }
  242.         end;
  243.     end;
  244. end;
  245.  
  246. {*********************************************************************}
  247. {* NetClose  : Closes a file.                                        *}
  248. {* Input     : File handle                                           *}
  249. {* Output    : None                                                  *}
  250. {*********************************************************************}
  251.  
  252. procedure NetClose( var DFile );
  253.  
  254. var regs : registers;        { Processor registers for interrupt call }
  255.  
  256. begin
  257.   if ( Filerec( DFile ).Mode <> fmClosed ) then          { File open? }
  258.     begin
  259.       with regs do
  260.         begin
  261.           ah := FCT_CLOSE;              { Function number: Close file }
  262.           bx := FileRec( DFile ).Handle;                { File handle }
  263.           msdos( regs );                             { Interrupt call }
  264.         end;
  265.       FileRec( DFile ).Mode := fmClosed;                 { Close file }
  266.       NetError := NE_OK;                                   { No error }
  267.       {ReleaseTimeSlice;  {Added by Bob Dalton - Gives up timeslice}
  268.     end
  269.   else
  270.     NetError := NE_InvalidHandle;                     { File not open }
  271. end;
  272.  
  273. {*********************************************************************}
  274. {* Locking     : Locks or unlocks a file range.                      *}
  275. {* Input       : File handle, operation, offset for start of file,   *}
  276. {*               length of range to be (un)locked                    *}
  277. {* Output      : TRUE if successful                                  *}
  278. {* Global var. : NetError/W (error status after call)                *}
  279. {* Info        : Call NetLock and NetUnlock for internal access only.*}
  280. {*********************************************************************}
  281.  
  282. function Locking( Handle    : word;
  283.                   Operation : byte;
  284.                   Offset    : longint;
  285.                   WrdLen    : longint ) : boolean;
  286.  
  287. var
  288.  regs : registers;        { Processor registers for interrupt call }
  289.  W101 : Word;
  290.  W102 : Word;
  291.  W103 : Boolean;
  292. begin
  293.   W101:=0;
  294.   W102:=0;
  295.   W103:=False;
  296.   
  297.   {Note: I have added a looping routine to this function which will
  298.   loop until it's successful OR 20,000 times (6-8 seconds) whichever
  299.   comes first. The loop is also designed to give up a time slice
  300.   every 100 iterations of the loop.  Bob Dalton} 
  301.   
  302.   Repeat
  303.    with regs do
  304.     begin
  305.       ah := FCT_REC_LOCK;        { Function number for interrupt call }
  306.       al := Operation;                         { 0 = Lock, 1 = Unlock }
  307.       bx := Handle;                                     { File handle }
  308.       cx := offset shr 16;                         { High word offset }
  309.       dx := offset and $FFFF;                       { Low word offset }
  310.       si := WrdLen shr 16;                         { High word length }
  311.       di := WrdLen and $FFFF;                       { Low word length }
  312.       msdos( regs );                                 { Interrupt call }
  313.       if ( ( flags and fcarry ) = 0 ) then      { Locking successful? }
  314.         begin
  315.           Locking := true;                                 { No error }
  316.           W103:=True;
  317.           NetError := NE_OK;
  318.         end
  319.       else
  320.         begin
  321.           Locking := false;
  322.           W103:=False;
  323.           NetError := ax;                         { Note error number }
  324.         end;
  325.      Inc(W101);
  326.      IF W101=100 then
  327.       Begin
  328.        Inc(W102);
  329.        {ReleaseTimeSlice;{Added by Bob Dalton - Gives up timeslice}
  330.        W101:=0;
  331.       End;
  332.     end;
  333.   UNTIL (W103=True) or (W102=200);
  334.  {ReleaseTimeSlice; {Added by Bob Dalton - Gives up timeslice}
  335. end;
  336.  
  337. {*********************************************************************}
  338. {* NetLock     : Locks records.                                      *}
  339. {* Input       : File, record number, number of records to be locked *}
  340. {* Output      : TRUE if successful                                  *}
  341. {* Global var. : NetError/W (error status after call)                *}
  342. {*********************************************************************}
  343.  
  344. function NetLock( var DFile;
  345.                       RecNo  : longint;
  346.                       RngNum : longint ) : boolean;
  347.  
  348. begin
  349.   NetLock := Locking( filerec( DFile ).Handle, 0,
  350.                       filerec( DFile ).Recsize * RecNo,
  351.                       filerec( DFile ).Recsize * RngNum );
  352. end;
  353.  
  354. {*********************************************************************}
  355. {* NetUnLock   : Unlocks locked records.                             *}
  356. {* Input       : File, record number, number of records to be locked *}
  357. {* Output      : TRUE if successful                                  *}
  358. {* Global var. : NetError/W (error status after call)                *}
  359. {*********************************************************************}
  360.  
  361. function NetUnlock( var DFile;
  362.                         RecNo  : longint;
  363.                         RngNum : longint ) : boolean;
  364. begin
  365.   NetUnLock := Locking( filerec( DFile).Handle, 1,
  366.                         filerec( DFile ).Recsize * RecNo,
  367.                         filerec( DFile ).Recsize * RngNum );
  368. end;
  369.  
  370. {*********************************************************************}
  371. {* Is_NetWriteOk : Enables file output.                              *}
  372. {* Input         : File                                              *}
  373. {* Output        : TRUE if output is enabled                         *}
  374. {*********************************************************************}
  375.  
  376. function Is_NetWriteOk( var DFile ) : boolean;
  377.  
  378. begin
  379.   with Filerec( DFile ) do
  380.     Is_NetWriteOk := ( Mode = fmOutput ) or ( Mode = fmInOut );
  381. end;
  382.  
  383. {*********************************************************************}
  384. {* Is_NetReadOk : Enables file input.                                *}
  385. {* Input        : File                                               *}
  386. {* Output       : TRUE if output is enabled                          *}
  387. {*********************************************************************}
  388.  
  389. function Is_NetReadOk( var DFile ) : boolean;
  390.  
  391. begin
  392.   with Filerec( DFile ) do
  393.     Is_NetReadOk := ( Mode = fmInput ) or ( Mode = fmInOut );
  394. end;
  395.  
  396. {*********************************************************************}
  397. {* Is_NetOpen  : Opens file.                                         *}
  398. {* Input       : File                                                *}
  399. {* Output      : TRUE if file is open                                *}
  400. {*********************************************************************}
  401.  
  402. function Is_NetOpen( var DFile ) : boolean;
  403.  
  404. begin
  405.   with Filerec( DFile ) do
  406.     Is_Netopen := ( Mode = fmInput ) or ( Mode = fmOutput ) or
  407.                ( Mode = fmInOut );
  408. end;
  409.  
  410. {*********************************************************************}
  411. {* NetWrite    : Writes to file.                                     *}
  412. {* Input       : File, data                                          *}
  413. {* Output      : None                                                *}
  414. {* Info        : Output is only possible in Pascal procedures when   *}
  415. {*               files have been opened in input-output mode.        *}
  416. {*               Attention: No type checking performed here.         *}
  417. {*********************************************************************}
  418.  
  419. procedure NetWrite( var DFile;
  420.                     var FData );
  421.  
  422. var regs : registers;        { Processor registers for interrupt call }
  423.  
  424. begin
  425.   with regs do
  426.     begin
  427.       ds := seg( FData );                              { Data address }
  428.       dx := ofs( FData );
  429.       ah := FCT_WRITE;                  { Function number: Write file }
  430.       bx := filerec( DFile ).Handle;                    { File handle }
  431.       cx := filerec( DFile ).Recsize;               { Number of bytes }
  432.       msdos( regs );                                 { Interrupt call }
  433.       if ( ( flags and fcarry ) = 0 ) then        { Write successful? }
  434.         NetError := NE_OK                                  { No error }
  435.       else
  436.         NetError := ax;                           { Note error number }
  437.     end;
  438. end;
  439.  
  440. {*********************************************************************}
  441. {* NetRead     : Reads from file.                                    *}
  442. {* Input       : File, variable for accessing data                   *}
  443. {* Output      : Data                                                *}
  444. {* Info        : Output is only possible in Pascal procedures when   *}
  445. {*               files have been opened in input-output mode.        *}
  446. {*               Attention: No type checking performed here.         *}
  447. {*********************************************************************}
  448.  
  449. procedure NetRead( var DFile;
  450.                    var FData );
  451.  
  452. var regs : registers;        { Processor registers for interrupt call }
  453.  
  454. begin
  455.   with regs do
  456.     begin
  457.       ds := seg( FData );                              { Data address }
  458.       dx := ofs( FData );
  459.       ah := FCT_READ;                    { Function number: Read file }
  460.       bx := filerec( DFile ).Handle;                    { File handle }
  461.       cx := filerec( DFile ).Recsize;               { Number of bytes }
  462.       msdos( regs );                                 { Interrupt call }
  463.       if ( ( flags and fcarry ) = 0 ) then        { Write successful? }
  464.         NetError := NE_OK                                  { No error }
  465.       else
  466.         NetError := ax;                           { Note error number }
  467.     end;
  468. end;
  469.  
  470. {*********************************************************************}
  471. {* NetSeek     : Sets file pointer.                                  *}
  472. {* Input       : File, record number                                 *}
  473. {* Output      : None                                                *}
  474. {* Info        : Output is only possible in Pascal procedures when   *}
  475. {*               files have been opened in input-output mode.        *}
  476. {*********************************************************************}
  477.  
  478. procedure NetSeek( var DFile;
  479.                        RecNo : longint );
  480.  
  481. var regs : registers;        { Processor registers for interrupt call }
  482.  
  483. begin
  484.   with regs do
  485.     begin
  486.       ah := FCT_LSEEK;            { Function number: Set file pointer }
  487.       al := 0;                  { Absolute position for start of file }
  488.       bx := filerec( DFile ).Handle;                    { File handle }
  489.       RecNo := RecNo * filerec( DFile ).Recsize;    { Offset in bytes }
  490.       cx := RecNo shr 16;                          { High word offset }
  491.       dx := recNo and $FFFF;                        { Low word offset }
  492.       msdos( regs );                                 { Interrupt call }
  493.       if ( ( flags and fcarry ) = 0 ) then        { Write successful? }
  494.         NetError := NE_OK                                  { No error }
  495.       else
  496.         NetError := ax;                           { Note error number }
  497.     end;
  498. end;
  499.  
  500. begin
  501. end.
  502.